﻿// ****************************************************************************** //
//     Module for all functions and variables used to move the frog properly.     //
//     The module handles also the logic to check if the frog is in the right     //
//               position for filling one of the 5 winning boxes.                 //
// ****************************************************************************** //

module FrogSimulation

open Frogger_Input
open FrogTypes
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Input
open Microsoft.Xna.Framework.Graphics
open Utilities
open Casanova
open Coroutines
open Math
open SI
open MapGrid
open GameState


//let mutable count_win = 0 //how many boxes filled so far?

let mutable indX = 8 //starting position index
let mutable indY = 0 //starting position index
let mutable indZ = 0 //starting position index

let mutable posX = road_x.[indX]
let mutable posY = road_y.[indY]
let mutable posZ = road_z.[indZ]

let mutable starting_position: bool = true  //true if the frog is in the first sidewalk position
let mutable win_trigger: int = 0       //used for sound: 0 = no sound, 1 = box filled, 2 = box not found

//function called to reset variables when the frog has 
let reset_state() =
    indX <- 8
    indY <- 0
    indZ <- 0
    posX <- road_x.[indX]
    posY <- road_y.[indY]
    posZ <- road_z.[indZ]
    starting_position <- true
    game_state.river_position <- false
    FrogTypes.reset_state()

//function to evaluate if the frog is in the right position for filling an empty box
let evaluate_win() =
    let mutable win = false
    for i in 0 .. 4 do
        let mutable (leftbound,rightbound) = win_boxes.[i]
        if indY <> 0 && frog_state.PositionX.Value > leftbound && frog_state.PositionX.Value < rightbound
        then
            if game_state.winbox_check.[i] = false
            then //the box can be filled
               win_trigger <- 1
               reset_state()
               game_state.winbox_check.[i] <- true
               game_state.count_win <- game_state.count_win + 1
               game_state.time_counter <- 0.0f
               win <- true

    if win = false then //box already filled or missed -> lost life
        win_trigger <- 2
        reset_state()
        game_state.Life <- game_state.Life - 1
        game_state.time_counter <- 0.0f



// ****************************************************************************** //
//                 Main update function to handle frog movements                  //
// ****************************************************************************** //
let update_frog() =
      co{ 
        do! yield_
        let state = Frogger_Input.InputHandler.GetState() //get the input state
        if indY <> 0 then starting_position <- false
        else 
            starting_position <- true
            win_trigger <- 0 //need the false here to stop respective sound
        if indY > 5 && indY < (road_y.Length - 1)
         then 
            game_state.river_position <- true
        else
            game_state.river_position <- false

        if indY = (road_y.Length - 1) then //if frog is in the last row
                evaluate_win()

        if state.left then
            if indX > 0 &&  game_state.river_position = false then
                indX <- indX - 1
                posX <- road_x.[indX]
                frog_state.PositionX := posX + frog_state.VelX
                frog_state.sphere.Center.X <- posX + frog_state.VelX
                if (!frog_state.RotationY <> 90.0f<deg>) then frog_state.RotationY := 90.0f<deg>
                    else frog_state.RotationY := !frog_state.RotationY
            elif  game_state.river_position = true  then
                System.Console.WriteLine("indY :" + (string)indY)
                frog_state.PositionX := !frog_state.PositionX - 4.0f + frog_state.VelX
                frog_state.sphere.Center.X <- frog_state.sphere.Center.X - 4.0f + frog_state.VelX
                if (!frog_state.RotationY <> 90.0f<deg>) then frog_state.RotationY := 90.0f<deg>
                    else frog_state.RotationY := !frog_state.RotationY
            else
                frog_state.PositionX  := !frog_state.PositionX + frog_state.VelX
                frog_state.sphere.Center.X <- frog_state.sphere.Center.X + frog_state.VelX


        elif state.right then
            if indX < (road_x.Length - 1) &&  game_state.river_position = false then
                indX <- indX + 1
                posX <- road_x.[indX]
                frog_state.PositionX := posX + frog_state.VelX
                frog_state.sphere.Center.X <- posX + frog_state.VelX
                if (!frog_state.RotationY <> -90.0f<deg>) then frog_state.RotationY := -90.0f<deg>
                    else frog_state.RotationY := !frog_state.RotationY
            elif  game_state.river_position = true  then
                frog_state.PositionX := !frog_state.PositionX + 4.0f + frog_state.VelX
                frog_state.sphere.Center.X <- frog_state.sphere.Center.X + 4.0f + frog_state.VelX
                if (!frog_state.RotationY <> -90.0f<deg>) then frog_state.RotationY := -90.0f<deg>
                    else frog_state.RotationY := !frog_state.RotationY
            else
                frog_state.PositionX  := !frog_state.PositionX + frog_state.VelX
                frog_state.sphere.Center.X <- frog_state.sphere.Center.X + frog_state.VelX


        elif state.up then
           if indY < (road_y.Length - 1) then
                indY <- indY + 1
                indZ <- indZ + 1
                if indY = road_y.Length - 1 then  game_state.river_position <- false
                posY <- road_y.[indY]
                posZ <- road_z.[indZ]
                frog_state.PositionY := posY
                frog_state.PositionZ := posZ
                frog_state.sphere.Center.Y <- posY
                frog_state.sphere.Center.Z <- posZ
                if (!frog_state.RotationY <> 0.0f<deg>) then frog_state.RotationY := 0.0f<deg>
                    else frog_state.RotationY := !frog_state.RotationY


        elif state.down then
            if indY > 0 && indY <> 6 then
                indY <- indY - 1
                indZ <- indZ - 1
                posY <- road_y.[indY]
                posZ <- road_z.[indZ]
                frog_state.PositionY := posY
                frog_state.PositionZ := posZ
                frog_state.sphere.Center.Y <- posY
                frog_state.sphere.Center.Z <- posZ
                if (!frog_state.RotationY <> 180.0f<deg>) then frog_state.RotationY := 180.0f<deg>
                    else frog_state.RotationY := !frog_state.RotationY
            else
               frog_state.PositionX  := !frog_state.PositionX + frog_state.VelX
               frog_state.sphere.Center.X <- frog_state.sphere.Center.X + frog_state.VelX
               frog_state.PositionY := posY
               frog_state.PositionZ := posZ

        else
                frog_state.PositionX  := !frog_state.PositionX + frog_state.VelX
                frog_state.sphere.Center.X <- frog_state.sphere.Center.X + frog_state.VelX
                frog_state.RotationY := !frog_state.RotationY
                frog_state.PositionY  := !frog_state.PositionY
                frog_state.PositionZ  := !frog_state.PositionZ

        return()
        }


let mutable private update_coroutine =
    repeat_ (update_frog ())

let mutable private main = update_frog()

let update_script() =
    update_coroutine <- update_ai update_coroutine
